<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<script src="../resources/common.js"></script>
</head>
<body>
<script>
// We use a single INPUT element for multiple testcases to improve test performance.
var input = document.createElement('input');
input.type = 'time';
document.body.appendChild(input);
input.focus();

function setDateTimeFormat(pattern) {
  getElementByPseudoId(internals.shadowRoot(input), '-webkit-datetime-edit').setAttribute('pattern', pattern);
  input.value = '';  // Updates the element for new format
}

function maybeUpdateAttribute(name, value) {
  if (value) {
    if (input.getAttribute(name) !== value)
      input.setAttribute(name, value);
  } else {
    if (input.hasAttribute(name))
      input.removeAttribute(name);
  }
}

function assert_input_value_with_limits(initial, step, min, max, keySequence, expected, expectedDisplayValue) {
  input.value = initial;
  maybeUpdateAttribute('min', min);
  maybeUpdateAttribute('max', max);
  maybeUpdateAttribute('step', step);

  keySequence.forEach(key => { eventSender.keyDown(key); });

  assert_equals(input.value, expected);
  if (expectedDisplayValue)
    assert_equals(getUserAgentShadowTextContent(input), expectedDisplayValue);
}

function assert_input_value_with_limits_after_up(initial, step, min, max, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, min, max, ['ArrowUp'], expected, expectedDisplayValue);
}

function assert_input_value_with_limits_after_down(initial, step, min, max, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, min, max, ['ArrowDown'], expected, expectedDisplayValue);
}

function assert_input_value_with_limits_after_deleteup(initial, step, min, max, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, min, max, ['Delete', 'ArrowUp'], expected, expectedDisplayValue);
}

function assert_input_value_with_limits_after_deletedown(initial, step, min, max, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, min, max, ['Delete', 'ArrowDown'], expected, expectedDisplayValue);
}

function assert_input_value_after_up(initial, step, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, null, null, ['ArrowUp'], expected, expectedDisplayValue);
}

function assert_input_value_after_down(initial, step, expected, expectedDisplayValue) {
  assert_input_value_with_limits(initial, step, null, null, ['ArrowDown'], expected, expectedDisplayValue);
}

// Hours, 1-12
test(() => {
  assert_own_property(window, 'internals');
  assert_own_property(window, 'eventSender');

  assert_input_value_after_up('07:00', 1, '08:00:00');
  assert_input_value_after_down('07:00', 1, '06:00:00');
  assert_input_value_after_up('11:00', 1, '12:00:00');
  assert_input_value_after_down('00:00', 1, '23:00:00');
  assert_input_value_after_up('06:00', 7200, '08:00');
  assert_input_value_after_down('06:00', 7200, '04:00');
  assert_input_value_after_up('10:00', 7200, '12:00');
  assert_input_value_after_down('00:00', 7200, '22:00');
  assert_input_value_after_up('07:00', 7200, '08:00');
  assert_input_value_after_down('07:00', 7200, '06:00');
  assert_input_value_after_up('06:00', 3601, '07:00:00');
  assert_input_value_after_down('06:00', 3601, '05:00:00');
  assert_input_value_after_up('06:00', 0, '07:00');
  assert_input_value_after_down('06:00', 0, '05:00');
  assert_input_value_after_up('06:00', 86400, '00:00');
  assert_input_value_after_down('06:00', 86400, '00:00');
  assert_input_value_after_up('06:00', 36000, '07:00');
  assert_input_value_after_down('06:00', 36000, '05:00');
  assert_input_value_with_limits_after_up('06:00', 7200, '01:00', null, '07:00');
  assert_input_value_with_limits_after_down('06:00', 7200, '01:00', null, '05:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '02:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '00:00', '12:00 AM');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '11:00');
  assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00:00');
  assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00:00');
  assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00:00');
  assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00:00');
  assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00:00');
  assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00:00');
  assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00:00');
  assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00:00');
  assert_input_value_with_limits_after_up('12:00', 1, '12:00', '15:00', '13:00:00');
  assert_input_value_with_limits_after_down('12:00', 1, '12:00', '15:00', '11:00:00');
  assert_input_value_with_limits_after_up('15:00', 1, '12:00', '15:00', '16:00:00');
  assert_input_value_with_limits_after_down('15:00', 1, '12:00', '15:00', '14:00:00');
  assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '13:00:00');
  assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '11:00:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '23:00:00');
  assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '16:00:00');
  assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '09:00:00');
  assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '20:00', '19:00');
  assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '20:00', '19:00');
  assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '18:00', '17:00');
  assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '18:00', '17:00');
  // Don't update am/pm if hours is initially blank
  assert_input_value_with_limits_after_up('', 60, '', '', '', '01:-- --');
  assert_input_value_with_limits_after_down('', 60, '', '', '', '12:-- --');
  assert_input_value_with_limits_after_up('', 43200, '', '', '', '12:00 --');
  assert_input_value_with_limits_after_down('', 43200, '', '', '', '12:00 --');
  // Check rollover for different steps
  assert_input_value_with_limits_after_up('12:00', 3600, '', '', '13:00');
  assert_input_value_with_limits_after_down('00:00', 3600, '', '', '23:00');
  assert_input_value_with_limits_after_up('12:00', 7200, '', '', '14:00');
  assert_input_value_with_limits_after_down('00:00', 7200, '', '', '22:00');
  assert_input_value_with_limits_after_up('12:00', 10800, '', '', '15:00');
  assert_input_value_with_limits_after_down('00:00', 10800, '', '', '21:00');
  assert_input_value_with_limits_after_up('12:00', 14400, '', '', '16:00');
  assert_input_value_with_limits_after_down('00:00', 14400, '', '', '20:00');
  assert_input_value_with_limits_after_up('12:00', 21600, '', '', '18:00');
  assert_input_value_with_limits_after_down('00:00', 21600, '', '', '18:00');
  assert_input_value_with_limits_after_up('12:00', 43200, '', '', '12:00');
  assert_input_value_with_limits_after_down('00:00', 43200, '', '', '00:00');
}, 'Hours, 1-12');

// Hours, 0-11
test(() => {
  assert_own_property(window, 'internals');
  assert_own_property(window, 'eventSender');
  setDateTimeFormat('KK:mm a');

  assert_input_value_after_up('11:00', 1, '00:00', '00:00 AM');
  assert_input_value_after_down('00:00', 1, '11:00', '11:00 AM');
  assert_input_value_after_up('23:00', 1, '12:00', '00:00 PM');
  assert_input_value_after_down('12:00', 1, '23:00', '11:00 PM');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '00:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '10:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '11:00');
  assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00');
  assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00');
  assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00');
  assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00');
  assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_up('12:00', 1, '12:00', '15:00', '13:00');
  assert_input_value_with_limits_after_down('12:00', 1, '12:00', '15:00', '15:00');
  assert_input_value_with_limits_after_up('15:00', 1, '12:00', '15:00', '12:00');
  assert_input_value_with_limits_after_down('15:00', 1, '12:00', '15:00', '14:00');
  assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '13:00');
  assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '23:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00');
  assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '16:00');
  assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '09:00');
  assert_input_value_with_limits_after_up('20:00', 7200, '17:00', '20:00', '17:00');
  assert_input_value_with_limits_after_down('20:00', 7200, '17:00', '20:00', '19:00');

  // Don't update am/pm if hours is initially blank
  assert_input_value_with_limits_after_up('', 60, '', '', '', '00:-- --');
  assert_input_value_with_limits_after_down('', 60, '', '', '', '11:-- --');
  assert_input_value_with_limits_after_up('', 43200, '', '', '', '00:00 --');
  assert_input_value_with_limits_after_down('', 43200, '', '', '', '00:00 --');
}, 'Hours, 0-11');

// Hours, 0-23
test(() => {
  assert_own_property(window, 'internals');
  assert_own_property(window, 'eventSender');
  setDateTimeFormat('HH:mm');

  assert_input_value_after_up('07:00', 1, '08:00');
  assert_input_value_after_down('07:00', 1, '06:00');
  assert_input_value_after_up('23:00', 1, '00:00');
  assert_input_value_after_down('00:00', 1, '23:00');
  assert_input_value_after_up('06:00', 7200, '08:00');
  assert_input_value_after_down('06:00', 7200, '04:00');
  assert_input_value_after_up('22:00', 7200, '00:00');
  assert_input_value_after_down('00:00', 7200, '22:00');
  assert_input_value_after_up('07:00', 7200, '08:00');
  assert_input_value_after_down('07:00', 7200, '06:00');
  assert_input_value_after_up('06:00', 3601, '07:00');
  assert_input_value_after_down('06:00', 3601, '05:00');
  assert_input_value_after_up('06:00', 0, '07:00');
  assert_input_value_after_down('06:00', 0, '05:00');
  assert_input_value_after_up('06:00', 86400, '00:00');
  assert_input_value_after_down('06:00', 86400, '00:00');
  assert_input_value_after_up('06:00', 36000, '07:00');
  assert_input_value_after_down('06:00', 36000, '05:00');
  assert_input_value_with_limits_after_up('06:00', 7200, '01:00', null, '07:00');
  assert_input_value_with_limits_after_down('06:00', 7200, '01:00', null, '05:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '00:00', '00:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '22:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '23:00');
  assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00');
  assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00');
  assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00');
  assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00');
  assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00');
  assert_input_value_with_limits_after_up('03:00', 1, '00:00', '03:00', '00:00');
  assert_input_value_with_limits_after_down('03:00', 1, '00:00', '03:00', '02:00');
  assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '10:00');
  assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '11:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '03:00');
  assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '10:00');
  assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '15:00');
  assert_input_value_with_limits_after_up('20:00', 7200, '17:00', '20:00', '17:00');
  assert_input_value_with_limits_after_down('20:00', 7200, '17:00', '20:00', '19:00');
}, 'Hours, 0-23');

// Hours, 1-24
test(() => {
  assert_own_property(window, 'internals');
  assert_own_property(window, 'eventSender');
  setDateTimeFormat('kk:mm');

  assert_input_value_after_up('11:00', 1, '12:00', '12:00');
  assert_input_value_after_down('00:00', 1, '23:00', '23:00');
  assert_input_value_after_up('23:00', 1, '00:00', '24:00');
  assert_input_value_after_down('12:00', 1, '11:00', '11:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, null, null, '02:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, null, null, '00:00');
  assert_input_value_with_limits_after_deleteup('06:00', 7200, '01:00', null, '01:00');
  assert_input_value_with_limits_after_deletedown('06:00', 7200, '01:00', null, '23:00');
  assert_input_value_with_limits_after_up('17:00', 1, '17:00', '20:00', '18:00');
  assert_input_value_with_limits_after_down('17:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('17:00', 1, '15:00', '17:00', '15:00');
  assert_input_value_with_limits_after_down('17:00', 1, '15:00', '17:00', '16:00');
  assert_input_value_with_limits_after_up('15:00', 1, '17:00', '20:00', '17:00');
  assert_input_value_with_limits_after_down('15:00', 1, '17:00', '20:00', '20:00');
  assert_input_value_with_limits_after_up('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_down('15:00', 1, '13:00', '13:00', '13:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '23:00');
  assert_input_value_with_limits_after_up('03:00', 1, '00:00', '03:00', '04:00');
  assert_input_value_with_limits_after_down('03:00', 1, '00:00', '03:00', '02:00');
  assert_input_value_with_limits_after_up('12:00', 1, '10:00', '12:00', '10:00');
  assert_input_value_with_limits_after_down('12:00', 1, '10:00', '12:00', '11:00');
  assert_input_value_with_limits_after_up('00:00', 1, '00:00', '03:00', '01:00');
  assert_input_value_with_limits_after_down('00:00', 1, '00:00', '03:00', '23:00');
  assert_input_value_with_limits_after_up('15:00', 1, '10:00', '15:00', '10:00');
  assert_input_value_with_limits_after_down('10:00', 1, '10:00', '15:00', '15:00');
  assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '20:00', '19:00');
  assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '20:00', '19:00');
  assert_input_value_with_limits_after_up('17:00', 7200, '17:00', '18:00', '17:00');
  assert_input_value_with_limits_after_down('17:00', 7200, '17:00', '18:00', '17:00');
}, 'Hours, 1-24');
</script>
</body>
</html>
